﻿namespace Spectral.Operations.Test
{
    using System;
    using NUnit.Framework;

    public sealed class OperatorTest
    {
        [Test]
        [TestCase(1)]
        [TestCase(1.0)]
        [TestCase(1f)]
        [TestCase(1L)]
        public void TestUnitProperty<T>(T value)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            Assert.That(Operator.One<T>(), Is.EqualTo(value));
        }

        [Test]
        [TestCase(2, 3, 2 + 3)]
        [TestCase(3.5, 1.2, 3.5 + 1.2)]
        [TestCase(7.0f, -3.6f, 7.0f + -3.6f)]
        [TestCase(1L, 6L, 1L + 6L)]
        public void TestAddMethod<T>(T left, T right, T result)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            Assert.That(Operator.Add(left, right), Is.EqualTo(result));
        }

        [Test]
        [TestCase(2, 3, 2 - 3)]
        [TestCase(3.5, 1.2, 3.5 - 1.2)]
        [TestCase(7.0f, -3.6f, 7.0f - -3.6f)]
        [TestCase(1L, 6L, 1L - 6L)]
        public void TestSubtractMethod<T>(T left, T right, T result)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            Assert.That(Operator.Subtract(left, right), Is.EqualTo(result));
        }

        [Test]
        [TestCase(2, 3, 2 * 3)]
        [TestCase(3.5, 1.2, 3.5 * 1.2)]
        [TestCase(7.0f, -3.6f, 7f * -3.6f)]
        [TestCase(1L, 6L, 1L * 6L)]
        public void TestMultiplyMethod<T>(T left, T right, T result)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            Assert.That(Operator.Multiply(left, right), Is.EqualTo(result));
        }

        [Test]
        [TestCase(2, 3, 2 / 3)]
        [TestCase(3.5, 1.2, 3.5 / 1.2)]
        [TestCase(7.0f, -3.6f, 7f / -3.6f)]
        [TestCase(1L, 6L, 1L / 6L)]
        public void TestDivideMethod<T>(T left, T right, T result)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            Assert.That(Operator.Divide(left, right), Is.EqualTo(result));
        }

        [Test]
        [TestCase(2, 3, 2 % 3)]
        [TestCase(3.5, 1.2, 3.5 % 1.2)]
        [TestCase(7.0f, -3.6f, 7f % -3.6f)]
        [TestCase(1L, 6L, 1L % 6L)]
        public void TestRemainderMethod<T>(T left, T right, T result)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            Assert.That(Operator.Remainder(left, right), Is.EqualTo(result));
        }

        [Test]
        [TestCase(2, -2)]
        [TestCase(3.5, -3.5)]
        [TestCase(-7.0f, 7.0f)]
        [TestCase(1L, -1L)]
        public void TestNegateMethod<T>(T value, T result)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            Assert.That(Operator.Negate(value), Is.EqualTo(result));
        }

        [Test]
        [TestCase(4, 2)]
        [TestCase(9.0, 3.0)]
        [TestCase(16f, 4f)]
        [TestCase(25L, 5L)]
        public void TestSqrtMethod<T>(T value, T result)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            Assert.That(Operator.Sqrt(value), Is.EqualTo(result));
        }

        [Test]
        [TestCase(4, 2, 16)]
        [TestCase(-1.0, 7, -1.0)]
        [TestCase(3f, 3f, 27f)]
        [TestCase(-2L, 11L, -2048L)]
        public void TestPowMethod<T>(T value, T power, T result)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            Assert.That(Operator.Pow(value, power), Is.EqualTo(result));
        }
    }
}
